#include <pthread.h>
#include <queue>
#include "Task.hpp"

namespace wyl
{
    const unsigned int default_capacity = 5;
    template <class T>
    class thread_pool
    {
    private:
        thread_pool(int capacity = default_capacity)
            : _capacity(capacity)
        {
            // 初始化锁和条件变量
            pthread_mutex_init(&_mutext, nullptr);
            pthread_cond_init(&_cond, nullptr);
        }
        ~thread_pool()
        {
            // 销毁锁和条件变量
            pthread_mutex_destroy(&_mutext);
            pthread_cond_destroy(&_cond);
        }
        thread_pool(const T &cp) = delete;

    private:
        std::queue<T> _sq;       // 任务队列
        unsigned int _capacity;  // 任务最大数量
        pthread_mutex_t _mutext; // 锁
        pthread_cond_t _cond;    // 条件变量
        bool Is_init = false;       // 线程是否初始化过
        static thread_pool<T> *_ins;

    private:
        void Lock()
        {
            pthread_mutex_lock(&_mutext);
        }
        void UnLock()
        {
            pthread_mutex_unlock(&_mutext);
        }
        bool Is_empty()
        {
            return 0 == _sq.size();
        }
        void Wait()
        {
            pthread_cond_wait(&_cond, &_mutext);
        }
        void WakeUp()
        {
            pthread_cond_signal(&_cond);
        }
        static void *Rountine(void *args)
        {
            pthread_detach(pthread_self()); // 线程分离i
            thread_pool<T> *tp = (thread_pool<T> *)args;
            while (true) // 线程一直处理任务
            {
                tp->Lock(); // 多个线程争夺锁
                // 判断任务队列是否为空
                while (tp->Is_empty())
                {
                    // 为空，等待任务生产
                    tp->Wait();
                }
                // 被唤醒，提取任务
                Task t;
                tp->Pop(&t);
                tp->UnLock(); // 解锁
                t();          // 任务已提取，该线程不需要抱着锁执行任务
            }
        }
        void Pop(T *out)
        {
            // 不需要上锁，因为当前线程正抱着锁
            *out = _sq.front();
            _sq.pop();
        }

        // 初始化线程池
        void pool_init()
        {
            if (!Is_init)
            {
                pthread_t tid;
                for (int i = 0; i < _capacity; i++)
                {
                    pthread_create(&tid, nullptr, Rountine, (void *)this);
                }
                Is_init = true;
            }
            else
                std::cout << "线程池已初始化" << std::endl;
        }

    public:
        static thread_pool<T> *GetThreadPool()
        {
            static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
            if (_ins == nullptr)
            {
                pthread_mutex_lock(&lock);
                if (_ins == nullptr)
                {
                    _ins = new thread_pool<T>();
                    _ins->pool_init();
                    std::cout << "线程池第一次创建" << std::endl;
                }
                pthread_mutex_unlock(&lock);
            }
            return _ins;
        }

        void Push(const T &in)
        {
            // 需要上锁，否则可能会出现多个线程把任务导进任务队列
            Lock();
            _sq.push(in);
            UnLock();
            // 有任务了，可以唤醒等待中的线程执行任务
            WakeUp();
        }
    };
    template<class T>
    thread_pool<T>* thread_pool<T>::_ins=nullptr;
}
